home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C/C++ Users Group Library 1996 July
/
C-C++ Users Group Library July 1996.iso
/
listings
/
v_09_12
/
9n12075a
< prev
next >
Wrap
Text File
|
1991-07-25
|
17KB
|
443 lines
/** LISTING 3 ** UARTLOW.C ***************************
Low level device driver routines for UART
*****************************************************/
#define UARTMAIN 1
#include <conio.h>
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <dos.h>
#include "uart.h"
#include "uartmacs.c"
/*
* Compile Options : /AL /Ox /Zp /c
* (Large library, optimization
* for maxium speed, pack structures).
* Note: /Ox does the following optimizations
* Relaxed alias checking
* Loop optimization
* Intrinsic substitution
* Optimization for speed
* Removing stack probing
*/
#pragma check_stack(off)
void interrupt far Asynch_driver(void)
{
register int value_from_port;
register int cur_char;
static unsigned char near cur_port;
static struct t_port_info *p_cur_port_info;
static int near interrupts_processed;
static int near i;
static char *p_temp;
static char tx_char;
/* Note - interrupts are automatically disabled by
CPU before entering interrupt routine. */
do
{ /* Loop until we make one complete pass
without processing any interrupts */
/* Set flag indicating that we haven't
processed any interrupts on this pass
through the loop yet. */
interrupts_processed = 0;
/* Address the port entry of the first port in
the system. */
p_cur_port_info = gp_port_info;
for (cur_port=1;cur_port<=g_num_ports;
cur_port++)
{ /* Loop through all the ports */
/* read port's interrupt identification register */
value_from_port = inp(p_cur_port_info->
base_address+INTERRUPT_IDENT_REGISTER);
if ( value_from_port & 0x01 )
{ /* No interrupt pending */
/* If less than MAX_RCVFIFO characters
have been read without receiving a
receive data interrupt, check line
status register to see if there is
still data in the FIFO. This code
will function correctly even if there
isn't a FIFO. */
if (p_cur_port_info->non_int_chars <
MAX_RCVFIFO)
{
/* read port's line status register */
value_from_port =
inp(p_cur_port_info->
base_address +
LINE_STATUS_REGISTER);
/* Delay for port to catch up */
IO_DELAY(1);
if ( value_from_port & 0x01 )
{ /* Data is ready */
/* Increment number of chars
processed from fifo without
interrupt */
p_cur_port_info->
non_int_chars++;
/* We have found at least one
interrupt pending so we will
have to make at least one
more pass. */
interrupts_processed = 1;
/* Skip normal interrupt
identification logic, and go
right to reading the data. */
goto force_read_data;
} /* End data is ready */
} /* End p_cur_port_info->
non_int_chars < MAX_RCVFIFO) */
} /* end no interrupt pending */
else
{ /* There is an interrupt pending
from this port */
/* We have found at least one interrupt
pending so we will have to make at
least one more pass. */
interrupts_processed = 1;
/* Mask out unwanted bits from interrupt
identification. */
value_from_port &= IIR_MASK;
switch (value_from_port)
{ /* Conditional execution depending
on type of interrupt */
/* Interrupt for Receiver Line
Status */
case 0x06 :
/* Clear receive register */
cur_char =
inp(p_cur_port_info->
base_address +
RECEIVE_REGISTER);
/* Clear high word of character
before breaking down error */
cur_char &= 0x00ff;
/* read port's line status
register */
value_from_port =
inp(p_cur_port_info->
base_address +
LINE_STATUS_REGISTER);
if (value_from_port & 0x10)
{ /* Received 'break' */
cur_char |= BREAK_SIGNAL;
}
if (value_from_port & 0x08)
{ /* framing error */
cur_char |= FRAMING_ERROR;
}
if (value_from_port & 0x04)
{ /* parity error */
cur_char |= PARITY_ERROR;
}
if (value_from_port & 0x02)
{ /* overrun error */
cur_char |= OVERRUN_ERROR;
}
goto add_char_to_rx_buf;
/* Interrupt for data received */
case 0x04 :
/* Check line status register to
see if data is ready */
value_from_port =
inp(p_cur_port_info->
base_address +
LINE_STATUS_REGISTER);
if ( !(value_from_port & 0x01) )
break;
/* Set number of characters
received without data receive
interrupt to 0. */
p_cur_port_info->
non_int_chars = 0;
force_read_data:
/* read received data
register */
cur_char =
inp(p_cur_port_info->
base_address+
RECEIVE_REGISTER);
/* Clear high word of character
before breaking down error */
cur_char &= 0x00ff;
add_char_to_rx_buf:
/* Calculate pointer to next
position in circular
receive buffer */
p_temp = p_cur_port_info->
a_receive_buffer +
p_cur_port_info->rx_tail;
/* Calculate next tail position
in receive buffer */
p_cur_port_info->rx_tail += 2;
if (p_cur_port_info->rx_tail >=
(BUFFER_SIZE * 2) )
p_cur_port_info->rx_tail = 0;
/* Check for receive buffer
overflow */
if (p_cur_port_info->rx_tail ==
p_cur_port_info->rx_head)
{ /* Receive buffer has